home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / public / SciAn / src / ScianWhisselFiles.c < prev    next >
C/C++ Source or Header  |  1994-08-01  |  18KB  |  649 lines

  1. /* 2/15/1993 ScianWhisselFiles.c
  2.  
  3. NEXRAD file reader */
  4.  
  5. #include "Scian.h"
  6. #include "ScianTypes.h"
  7. #include "ScianArrays.h"
  8. #include "ScianIcons.h"
  9. #include "ScianWindows.h"
  10. #include "ScianObjWindows.h"
  11. #include "ScianVisWindows.h"
  12. #include "ScianVisObjects.h"
  13. #include "ScianControls.h"
  14. #include "ScianColors.h"
  15. #include "ScianDialogs.h"
  16. #include "ScianFiles.h"
  17. #include "ScianFileSystem.h"
  18. #include "ScianLists.h"
  19. #include "ScianPictures.h"
  20. #include "ScianErrors.h"
  21. #include "ScianTimers.h"
  22. #include "ScianDatasets.h"
  23. #include "ScianFilters.h"
  24. #include "ScianTextBoxes.h"
  25. #include "ScianTitleBoxes.h"
  26. #include "ScianButtons.h"
  27. #include "ScianSliders.h"
  28. #include "ScianScripts.h"
  29. #include "ScianIDs.h"
  30. #include "ScianVisContours.h"
  31. #include "ScianStyle.h"
  32. #include "ScianSpaces.h"
  33. #include "ScianMethods.h"
  34. #include "ScianObjFunctions.h"
  35. #include "ScianWhisselFiles.h"
  36.  
  37. #include <time.h>
  38.  
  39. #ifndef ELEVATIONSKIP
  40. #define ELEVATIONSKIP        1100
  41. #define RADIALSKIP        1101
  42. #define GATESKIP                1102    
  43. #define DOREFDATASETS           1103
  44. #define DOVELDATASETS           1104
  45. #endif
  46.  
  47. #define TORADS (3.1415926535898 / 180.0)    /* deg -> rad conversion
  48.                            factor */
  49. #ifndef RELEASE
  50.  
  51. #ifdef PROTO
  52. void skip_ray(int c, FILE *f)
  53. #else
  54. void skip_ray(c, f)
  55.   int c;
  56.   FILE *f;
  57. #endif
  58. {
  59.   while(c--)
  60.     getc(f);
  61. }
  62.  
  63. #ifdef PROTO
  64. static ObjPtr ReadNXRFile(ObjPtr reader, char *name)
  65. #else
  66. static ObjPtr ReadNXRFile(reader, name)
  67.   ObjPtr  reader;
  68.   char   *name;
  69. #endif
  70. {
  71.   struct NXRhead header;    /* NEXRAD/SciAn file header */
  72.   FILE   *infile;
  73.  
  74.   char    formname[TEMPSTRSIZE];
  75.   char    refname[TEMPSTRSIZE];
  76.   char    velname[TEMPSTRSIZE];
  77.   char   *tc;
  78.  
  79.   int     els = 0;    /* Number of elevations */
  80.   int     i, j, k;    /* Index variables */
  81.   int     ii, ji, ki;
  82.  
  83.   float   x, y, z, len, inc;    /* Used in grid-positioning calculations */
  84.   float   sinz, cosz, cosr, sinr;
  85.   float *cosa, *sina, *h, *s;
  86.   float ae = (4.0 * 6371.0) / 3.0; /* Effective Radius of the Earth */
  87.  
  88.   float ref_value_array[256];    /* Array of byte-to-float values for
  89.                    compressed dataset format */
  90.   float vel_value_array[256];
  91.  
  92.   ObjPtr  RefForm = NULL;    /* Dataforms for Reflectivity */
  93.   ObjPtr  VelForm = NULL;    /* and Velocity */
  94.   ObjPtr  form = NULL;    /* Temp form pointer */
  95.  
  96.   ObjPtr  RefDataSet, VelDataSet;    /* Datasets for reflec. and vel. */
  97.  
  98.   long    dims[3];
  99.   real    bounds[6];    /* Used to define parameters of datasets */
  100.   long    indices[3];    /* and dataforms */
  101.  
  102.   float   val;            /* Conversion vars */
  103.   unsigned char uchar;
  104.   int     elcount, ncount, count;
  105.   int sum;
  106.  
  107.   int elskip = 0, radskip = 0, gateskip = 3;
  108.   int radmod, gatemod, elmod;
  109.   int doref = 1, dovel = 0;
  110.  
  111.   ObjPtr var;
  112.  
  113.   var = GetIntVar("ReadNXRFile", reader, DOREFDATASETS);
  114.   if (!var)
  115.     doref = 1;
  116.   else
  117.     doref = GetInt(var);
  118.  
  119.   var = GetIntVar("ReadNXRFile", reader, DOVELDATASETS);
  120.   if (!var)
  121.     dovel = 1;
  122.   else
  123.     dovel = GetInt(var);
  124.  
  125.   var = GetRealVar("ReadNXRFile", reader, ELEVATIONSKIP);
  126.   if (!var)
  127.     elskip = 0;
  128.   else
  129.     elskip = (int)GetReal(var);
  130.  
  131.   var = GetRealVar("ReadNXRFile", reader, RADIALSKIP);
  132.   if (!var)
  133.     radskip = 0;
  134.   else
  135.     radskip = (int)GetReal(var);
  136.  
  137.   var = GetRealVar("ReadNXRFile", reader, GATESKIP);
  138.   if (!var)
  139.     gateskip = 0;
  140.   else
  141.     gateskip = (int)GetReal(var);
  142.  
  143.   elmod = elskip + 1;
  144.   radmod = radskip + 1;
  145.   gatemod = gateskip + 1;
  146.  
  147.   /* Derive a dataset name from the file name */
  148.  
  149.   strcpy(formname, name);
  150.   tc = formname;
  151.   while (*tc && (*tc != '@') && (*tc != '.'))
  152.     tc++;
  153.   *tc = '\0';
  154.   strcpy(refname, formname);
  155.   strcpy(velname, formname);
  156.  
  157.   strcat(formname, ".form");
  158.   strcat(refname, ".dBZ");
  159.   strcat(velname, ".m/s");
  160.  
  161.   /* Open the file and verify that it contains appropriate data */
  162.  
  163.   if ((infile = fopen(name, "r")) == NULL) {
  164.     FileFormatError("ReadNXRFile", "File not accessible");
  165.     return NULLOBJ;
  166.   }
  167.   if (fread(&header, sizeof(header), 1, infile) != 1) {
  168.     FileFormatError("ReadNXRFile", "Error reading file header");
  169.     fclose(infile);
  170.     return NULLOBJ;
  171.   }
  172.   if (strncmp(header.ident, FVERSION, 6) != 0) {
  173.     FileFormatError("ReadNXRFile", "File is not a NEXRAD file");
  174.     fclose(infile);
  175.     return NULLOBJ;
  176.   }
  177.   if (strncmp(header.ident, FVERSION, 7) != 0) {
  178.     FileFormatError("ReadNXRFile", 
  179.             "File and reader versions are incompatible");
  180.     fclose(infile);
  181.     return NULLOBJ;
  182.   }
  183.  
  184.   /* Count the number of elevations to be read. */
  185.  
  186.   fprintf(stderr, "Els=%d\n", header.num_els);
  187.  
  188.   if (elskip) {
  189.     for (i=0,els=0; i < header.num_els; i++) {
  190.       if (!(i % elmod) || (i==header.num_els-1))
  191.     els++;
  192.     }
  193.   } else
  194.     els = header.num_els;
  195.  
  196.   /* Establish the grid point dimensions. */
  197.  
  198.   dims[0] = els;
  199.   dims[1] = (int)fceil((double)N_RADS / (double)radmod);
  200.   dims[2] = (int)fceil((double)N_REFGATES / (double)gatemod);
  201.  
  202.   /* 
  203.     Build a grid for placing data.  Use the reflectivity gate spacing
  204.     for both reflectivity and velocity data for the purposes of data
  205.     reduction (velocity data is 4x as dense, but covers half the distance).
  206.   */
  207.  
  208.   form = NewDataset(formname, 3, dims, 3);
  209.   SetCurField(FIELD1, form);
  210.  
  211.   /* Precalculate the sin/cos of all the radials since these
  212.      will be the same for each elevation angle (saves a few
  213.      thousand sin/cos calls). */
  214.  
  215.   cosa = (float *)Alloc(N_RADS * sizeof(float));
  216.   sina = (float *)Alloc(N_RADS * sizeof(float));
  217.  
  218.   for (j=0; j < N_RADS; j++) {
  219.     /* Convert from radial number to sin/cos of the degree
  220.        measure of that radial.  Radials are numbered clockwise
  221.        starting 0.5 degrees east of north. */
  222.     cosa[j] = (float) cos((double) (90.0 - (j + 0.5)) * TORADS);
  223.     sina[j] = (float) sin((double) (90.0 - (j + 0.5)) * TORADS);
  224.   }
  225.   
  226.   h = (float *)Alloc(N_REFGATES * sizeof(float));
  227.   s = (float *)Alloc(N_REFGATES * sizeof(float));
  228.  
  229.   inc = (float) header.ref_gatespace / 1000.0;
  230.  
  231.   for (i=0, ii=0; i < header.num_els; i++) {    /* elevation loop */
  232.  
  233.     fprintf(stderr,"Doing loop %d\n", i);
  234.     /* Are we skipping this elevation? */
  235.     if ((i % elmod) && (i<header.num_els-1)) {
  236.       continue;
  237.     }
  238.  
  239.     indices[0] = ii++;
  240.  
  241.     /* Cache the sin/cos values for this elevation angle. */
  242.  
  243.     sinz = sin((double) (header.elevs[i]*TORADS));
  244.     cosz = cos((double) (header.elevs[i]*TORADS));
  245.  
  246.     /* Establish heights and distances for any given ray in
  247.        the current elevation scan. */
  248.  
  249.     for (k=0, len=inc/2.0; k < N_REFGATES; k++, len += inc) {
  250.       /* Given the distance of the gate (len), h is the height
  251.      above the surface of the earth accounting for curvature. */
  252.       h[k] = sqrt((double) (len*len + ae*ae + 2.0*len*ae*sinz)) - ae;
  253.       
  254.       /* s is distance along the surface of the earth to the point
  255.      underneath the grid point accounting for the curvature. */ 
  256.       s[k] = ae * asin((double)((len*cosz)/(ae + h[k]))); 
  257.     }
  258.  
  259.     if (i == 0)    {        /* Set x and y bounds from the smallest
  260.                    elevation angle.  */
  261.       bounds[0] = -s[N_REFGATES-1];
  262.       bounds[1] = s[N_REFGATES-1];
  263.       bounds[2] = -s[N_REFGATES-1];
  264.       bounds[3] = s[N_REFGATES-1];
  265.       bounds[4] = h[0];
  266.     } else if (i == header.num_els-1) {    /* Set z max from the greatest
  267.                        elevation angle. */
  268.       bounds[5] = h[N_REFGATES-1];
  269.     }
  270.  
  271.     for (j=0, ji=0; j < N_RADS; j++) { /* radial loop */
  272.  
  273.       if (!(j % radmod)) {
  274.     indices[1] = ji++;
  275.  
  276.     cosr = cosa[j];
  277.     sinr = sina[j];
  278.  
  279.     for (k=0, ki=0; k < N_REFGATES; k++) {
  280.       if (!(k % gatemod)) {
  281.         z = h[k];
  282.         x = s[k] * cosr;
  283.         y = s[k] * sinr;
  284.  
  285.         indices[2] = ki++;
  286.       
  287.         PutFieldComponent(FIELD1, 0, indices, x);
  288.         PutFieldComponent(FIELD1, 1, indices, y);
  289.         PutFieldComponent(FIELD1, 2, indices, z);
  290.       }
  291.     }
  292.       }
  293.     }
  294.   }
  295.  
  296.   Free(sina);
  297.   Free(cosa);
  298.   Free(h);
  299.   Free(s);
  300.  
  301.   /* Now that the grid has been created, turn it into a dataform. */
  302.  
  303.   RefForm = NewCurvilinearDataForm(formname, 3, dims, bounds, form);
  304.  
  305.   /* Now setup the complete datasets. */
  306.  
  307.   if (doref) {
  308.     for (i=2; i < 256; i++) {
  309.       ref_value_array[i] = (float)(i - 2) / 2.0 - 32.0;
  310.     }
  311.     ref_value_array[0] = ref_value_array[1] = missingData;
  312.  
  313.     RefDataSet = NewCompressedDataset(refname, 3, dims, 0, ref_value_array);
  314.     SetDatasetForm(RefDataSet, RefForm);
  315.   }
  316.   if (dovel) {
  317.     if (header.vel_res == 2) {
  318.       for (i=2; i < 256; i++) {
  319.     vel_value_array[i] = (float)(i - 2) / 2.0 - 63.5;
  320.       }
  321.     } else {
  322.       for (i=2; i < 256; i++) {
  323.     vel_value_array[i] = (float)(i - 129);
  324.       }
  325.     }
  326.     vel_value_array[0] = vel_value_array[1] = missingData;
  327.  
  328.     VelDataSet = NewCompressedDataset(velname, 3, dims, 0, vel_value_array);
  329.     SetDatasetForm(VelDataSet, RefForm);
  330.   }
  331.  
  332.   /* Read and convert data: for each elevation, reflectivity is first, 
  333.      then velocity data. */
  334.  
  335.   for (i=0, ii=0; i < header.num_els; i++) {
  336.     if ((i % elmod) && (i < header.num_els-1)) {
  337.       skip_ray(N_RADS * (N_REFGATES + N_VELGATES), infile);
  338.       continue;
  339.     }
  340.  
  341.     indices[0] = ii++;
  342.  
  343.     if (doref) {        /* Creating Reflectivity datasets? */
  344.       fprintf(stderr, "Doing ref elev %d\n", i);
  345.       SetCurField(FIELD1, RefDataSet);
  346.       for (j=0, ji=0; j < N_RADS; j++) {
  347.     if (j % radmod)
  348.       skip_ray(N_REFGATES, infile);
  349.     else {
  350.       indices[1] = ji++;
  351.       if (feof(infile))
  352.         goto READERROR;
  353.       for (k=0, ki=0; k < N_REFGATES; k++) {
  354.         uchar = (unsigned char) getc(infile);
  355.         if (!(k % gatemod)) {
  356.           indices[2] = ki++;
  357.       /* val = (uchar <= 1) ? missingData : (uchar - 2) / 2.0 - 32.0; */
  358.           PutCompressedFieldComponent(FIELD1, 0, indices, uchar);
  359.         }
  360.       }
  361.     }
  362.       }
  363.     } else {
  364.       skip_ray(N_RADS * N_REFGATES, infile);
  365.     }
  366.  
  367.     if (dovel) {        /* Creating Velocity datasets? */
  368.       /* Read velocity scan using one of two resolution values */
  369.       fprintf(stderr, "Doing vel elev %d\n", i);
  370.       SetCurField(FIELD1, VelDataSet);
  371.       for (j=0, ji=0; j < N_RADS; j++) {
  372.     if (j % radmod) {
  373.       skip_ray(N_VELGATES, infile);
  374.     } else {
  375.       elcount = 0;
  376.       sum = 0;
  377.       ncount = 0;
  378.       indices[1] = ji++;
  379.       if (feof(infile))
  380.         goto READERROR;
  381.       for (k=0, ki=0; k < N_VELGATES; k++) {
  382.         elcount += header.vel_gatespace;
  383.         uchar = (unsigned char) getc(infile);
  384.         if (uchar > 1) {
  385.           sum += uchar;
  386.           ncount++;
  387.         }
  388.         if (elcount >= header.ref_gatespace * gatemod) {
  389.           elcount %= header.ref_gatespace * gatemod;
  390.           indices[2] = ki++;
  391.           if (ncount)
  392.         uchar = (unsigned char)((float)sum / (float)ncount + 0.5);
  393.           else
  394.         uchar = 0;
  395.           PutCompressedFieldComponent(FIELD1, 0, indices, uchar);
  396.           sum = 0;
  397.           ncount = 0;
  398.         }
  399.       }
  400.       for (; ki < dims[2]; ki++) {
  401.         indices[2] = ki;
  402.         PutCompressedFieldComponent(FIELD1, 0, indices, (unsigned char)0);
  403.       }
  404.     }
  405.       }
  406.     } else {    
  407.       /* Skip velocity scan */
  408.       skip_ray(N_RADS * N_VELGATES, infile);
  409.     }        /* end if (do velocity dataset) */
  410.   }    /* end elevation loop */
  411.  
  412.   fclose(infile);
  413.  
  414.   /* The UNIX concept of time (i.e., seconds since 1/1/70 UTC) is
  415.      used to express the time of the radar picture.  SciAn wants
  416.      seconds since midnight, so convert appropriately. */
  417.   {
  418.     struct tm the_time;
  419.     time_t clocktime, result_time;
  420.     extern long _timezone, _altzone, _daylight;
  421.  
  422.     clocktime = (time_t) header.file_time;
  423.     memcpy((void *)&the_time, (void *)gmtime(&clocktime),
  424.        sizeof(struct tm));
  425.     /* Reset to midnight of the current day... */
  426.     the_time.tm_sec = 0;
  427.     the_time.tm_min = 0;
  428.     the_time.tm_hour = 0;
  429.     /* 
  430.       Obtain the clock time at midnight. The SG documentation says
  431.       mktime() converts from the local timezone domain, so subtract
  432.       the difference in seconds between the local time zone and GMT
  433.       so that the result will be GMT.
  434.     */
  435.     result_time = mktime(&the_time);
  436.     if (_daylight)
  437.       result_time -= _altzone;
  438.     else
  439.       result_time -= _timezone;
  440.     val = (float)(clocktime - result_time);
  441.   }
  442.  
  443.   val += 3600.0;
  444.  
  445.   if (doref)
  446.     RegisterTimeDataset(RefDataSet, val);
  447.   if (dovel)
  448.     RegisterTimeDataset(VelDataSet, val);
  449.  
  450.   return NULLOBJ;
  451.  
  452. READERROR:
  453.   FileFormatError("ReadNXRFile", "Premature EOF!");
  454.   fclose(infile);
  455.   return NULLOBJ;
  456. }
  457.  
  458. #endif
  459.  
  460. #ifdef PROTO
  461. void    KillWhisselFiles(void)
  462. #else
  463. void    KillWhisselFiles()
  464. #endif
  465. {
  466. }
  467.  
  468. #ifndef RELEASE
  469. #define NXR_ITEMWIDTH 225
  470. #define NXR_MIDDLE_SEP 45
  471. #define NXR_SMALLER_ITEM 180
  472.  
  473. #ifdef PROTO
  474. static ObjPtr    AddNXRControls(ObjPtr FileReader, ObjPtr PanelContents)
  475. #else
  476. static ObjPtr    AddNXRControls(FileReader, PanelContents)
  477.   ObjPtr  FileReader, PanelContents;
  478. #endif
  479. {
  480.   ObjPtr  checkbox, textbox, var;
  481.   int     left, right, bottom, top;
  482.  
  483.   bottom = left = MAJORBORDER;
  484.  
  485.   top = bottom + CHECKBOXHEIGHT;
  486.   right = left + NXR_ITEMWIDTH;
  487.  
  488.   /* If DOREFDATASETS has not been created yet, create it and set
  489.      it to TRUE. */
  490.  
  491.   var = GetIntVar("AddNXRControls", FileReader, DOREFDATASETS);
  492.   if (!var)
  493.     SetVar(FileReader, DOREFDATASETS, ObjTrue);
  494.   checkbox = NewCheckBox(left, right, bottom, top,
  495.              "Create Reflectivity Datasets",
  496.              GetPredicate(FileReader, DOREFDATASETS));
  497.   PrefixList(PanelContents, checkbox);
  498.   SetVar(checkbox, PARENT, PanelContents);
  499.   SetVar(checkbox, HELPSTRING, NewString("This option determines whether or \
  500. not reflectivity datasets are generated."));
  501.   AssocDirectControlWithVar(checkbox, FileReader, DOREFDATASETS);
  502.  
  503.   left = right + NXR_MIDDLE_SEP;
  504.   right = left + NXR_ITEMWIDTH;
  505.  
  506.   /* If DOVELDATASETS has not been created yet, create it and set
  507.      it to TRUE. */
  508.  
  509.   var = GetIntVar("AddNXRControls", FileReader, DOVELDATASETS);
  510.   if (!var)
  511.     SetVar(FileReader, DOREFDATASETS, ObjTrue);
  512.   checkbox = NewCheckBox(left, right, bottom, top,
  513.              "Create Velocity Datasets",
  514.              GetPredicate(FileReader, DOVELDATASETS));
  515.   PrefixList(PanelContents, checkbox);
  516.   SetVar(checkbox, PARENT, PanelContents);
  517.   SetVar(checkbox, HELPSTRING, NewString("This option determines whether or \
  518. not Doppler velocity datasets are generated."));
  519.   AssocDirectControlWithVar(checkbox, FileReader, DOVELDATASETS);
  520.  
  521.   left = MAJORBORDER;
  522.   right = left + NXR_SMALLER_ITEM;
  523.   bottom = top + MINORBORDER;
  524.   top = bottom + EDITBOXHEIGHT;
  525.  
  526.   /* Elevation Skip Factors */
  527.   textbox = NewTextBox(left, right, bottom, top,
  528.              0, "Elevation Skip Text", "Elevation Skip Factor:");
  529.   SetVar(textbox, PARENT, PanelContents);
  530.   PrefixList(PanelContents, textbox);
  531.  
  532.   left = right + NXR_MIDDLE_SEP;
  533.   right = left + NXR_ITEMWIDTH;
  534.   
  535.   var = GetRealVar("AddNXRControls", FileReader, ELEVATIONSKIP);
  536.   if (!var)
  537.     SetVar(FileReader, ELEVATIONSKIP, NewReal(0.0));
  538.   textbox = NewTextBox(left, right, bottom, top,
  539.                EDITABLE + WITH_PIT + ONE_LINE,
  540.                "Elevation Skip", "0");
  541.   SetVar(textbox, PARENT, PanelContents);
  542.   PrefixList(PanelContents, textbox);
  543.   SetTextAlign(textbox, RIGHTALIGN);
  544.   AssocTextRealControlWithVar(textbox, FileReader, ELEVATIONSKIP, 
  545.                   0, plusInf, TR_NE_TOP);
  546.   SetVar(textbox, HELPSTRING,
  547.      NewString("This value indicates the number of elevation \
  548. scans to skip.  The bottom and top elevation angles are always used, \
  549. regardless of this value."));
  550.  
  551.   left = MAJORBORDER;
  552.   right = left + NXR_SMALLER_ITEM;
  553.   bottom = top + MINORBORDER;
  554.   top = bottom + EDITBOXHEIGHT;
  555.  
  556.   /* Radial Skip Factors */
  557.   textbox = NewTextBox(left, right, bottom, top,
  558.                0, "Radial Skip Text", "Radial Skip Factor:");
  559.   SetVar(textbox, PARENT, PanelContents);
  560.   PrefixList(PanelContents, textbox);
  561.  
  562.   left = right + NXR_MIDDLE_SEP;
  563.   right = left + NXR_ITEMWIDTH;
  564.  
  565.   var = GetRealVar("AddNXRControls", FileReader, RADIALSKIP);
  566.   if (!var)
  567.     SetVar(FileReader, RADIALSKIP, NewReal(0.0));
  568.   textbox = NewTextBox(left, right, bottom, top,
  569.                EDITABLE + WITH_PIT + ONE_LINE,
  570.                "Radial Skip", "0");
  571.   SetVar(textbox, PARENT, PanelContents);
  572.   PrefixList(PanelContents, textbox);
  573.   SetTextAlign(textbox, RIGHTALIGN);
  574.   AssocTextRealControlWithVar(textbox, FileReader, RADIALSKIP, 
  575.                   0, plusInf, TR_NE_TOP);
  576.   SetVar(textbox, HELPSTRING,
  577.      NewString("This value indicates the number of radials (beams) \
  578. skipped."));
  579.  
  580.   left = MAJORBORDER;
  581.   right = left + NXR_SMALLER_ITEM;
  582.   bottom = top + MINORBORDER;
  583.   top = bottom + EDITBOXHEIGHT;
  584.  
  585.   /* Gate Skip Factors */
  586.   textbox = NewTextBox(left, right, bottom, top,
  587.                0, "Gate Skip Text", "Gate Skip Factor:");
  588.   SetVar(textbox, PARENT, PanelContents);
  589.   PrefixList(PanelContents, textbox);
  590.  
  591.   left = right + NXR_MIDDLE_SEP;
  592.   right = left + NXR_ITEMWIDTH;
  593.  
  594.   var = GetRealVar("AddNXRControls", FileReader, GATESKIP);
  595.   if (!var)
  596.     SetVar(FileReader, GATESKIP, NewReal(0.0));
  597.   textbox = NewTextBox(left, right, bottom, top,
  598.                EDITABLE + WITH_PIT + ONE_LINE,
  599.                "Gate Skip", "0");
  600.   SetVar(textbox, PARENT, PanelContents);
  601.   PrefixList(PanelContents, textbox);
  602.   SetTextAlign(textbox, RIGHTALIGN);
  603.   AssocTextRealControlWithVar(textbox, FileReader, GATESKIP, 
  604.                   0, plusInf, TR_NE_TOP);
  605.   SetVar(textbox, HELPSTRING,
  606.      NewString("This value indicates the number of gates \
  607. to skip during file reading."));
  608.  
  609.   return NULLOBJ;
  610. }
  611.  
  612. #endif
  613.  
  614. #ifdef PROTO
  615. void    InitWhisselFiles(void)
  616. #else
  617. void    InitWhisselFiles()
  618. #endif
  619. {
  620. #ifndef RELEASE
  621.   ObjPtr  fileReader;
  622.  
  623.   fileReader = NewFileReader("NXR");
  624.   SetVar(fileReader, EXTENSION, NewString("nxr"));
  625.   SetVar(fileReader, HELPSTRING,
  626.      NewString("This file reader ingests NEXRAD (NEXt generation RADar) \
  627. volume scans which have been pre-processed by a tape-to-disk file \
  628. converter.  Since NEXRAD volume scans can be quite large, file reader \
  629. options have been provided to reduce the amount of data processed."));
  630.   SetMethod(fileReader, READALL, ReadNXRFile);
  631.   SetMethod(fileReader, ADDCONTROLS, AddNXRControls);
  632.  
  633.   SetVar(fileReader, DOREFDATASETS, ObjTrue);
  634.   SetVar(fileReader, DOVELDATASETS, ObjTrue);
  635.   SetVar(fileReader, ELEVATIONSKIP, NewReal(0.0));
  636.   SetVar(fileReader, RADIALSKIP, NewReal(0.0));
  637.   SetVar(fileReader, GATESKIP, NewReal(0.0));
  638.  
  639.   /*EMP added save setting stuff*/
  640.   AddSnapVar(fileReader, DOREFDATASETS);
  641.   AddSnapVar(fileReader, DOVELDATASETS);
  642.   AddSnapVar(fileReader, ELEVATIONSKIP);
  643.   AddSnapVar(fileReader, RADIALSKIP);
  644.   AddSnapVar(fileReader, GATESKIP);
  645.   ApplySavedSettings(fileReader);
  646.  
  647. #endif
  648. }
  649.